Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 12 Arbeiten mit Dateien und Streams
  gp 12.1 Einführung
  gp 12.2 Namespaces der Ein- bzw. Ausgabe
    gp 12.2.1 Das Behandeln von Ausnahmen bei E/A-Operationen
  gp 12.3 Laufwerke, Verzeichnisse und Dateien
    gp 12.3.1 Die Klasse »File«
    gp 12.3.2 Die Klasse »FileInfo«
    gp 12.3.3 Die Klassen »Directory« und »DirectoryInfo«
    gp 12.3.4 Die Klasse »Path«
    gp 12.3.5 Die Klasse »DriveInfo«
    gp 12.3.6 Die Klasse »SpecialDirectories«
  gp 12.4 Die »Stream«-Klassen
    gp 12.4.1 Die abstrakte Klasse »Stream«
    gp 12.4.2 Die von »Stream« abgeleiteten Klassen im Überblick
    gp 12.4.3 Die Klasse »FileStream«
  gp 12.5 Die Klassen »TextReader« und »TextWriter«
    gp 12.5.1 Die Klasse »StreamWriter«
    gp 12.5.2 Die Klasse »StreamReader«
    gp 12.5.3 Die Klassen »StringWriter« und »StringReader«
  gp 12.6 Die Klassen »BinaryReader« und »BinaryWriter«
    gp 12.6.1 Komplexe binäre Dateien
  gp 12.7 Synchrone und asynchrone Operationen
    gp 12.7.1 Beispielprogramm eines asynchronen Schreibvorgangs


Galileo Computing

12.4 Die »Stream«-Klassen  downtop

Ein Stream ist die abstrahierte Darstellung eines Datenflusses aus einer geordneten Abfolge von Bytes. Welcher Natur dieser Datenstrom ist, ob er aus einer Datei stammt, ob er die Eingabe eines Benutzers an der Tastatur enthält oder möglicherweise aus einer Netzwerkverbindung bezogen wird, bleibt zunächst einmal offen. Die Beschaffenheit des Datenflusses hängt nicht nur von Sender und Empfänger ab, sondern auch ganz entscheidend vom Betriebssystem.

Ein Entwickler soll seine Aufgabe unabhängig von diesen spezifischen Details lösen. E/A-Streams werden deshalb von Klassen beschrieben, die Allgemeingültigkeit garantieren. Das spielt insbesondere bei der Entwicklung von .NET-Anwendungen eine wesentliche Rolle, um die Plattformunabhängigkeit des Codes zu gewährleisten.

Streams dienen generell dazu, drei elementare Operationen ausführen zu können:

gp  Dateninformationen müssen in einen Sream geschrieben werden. Nach welchem Muster das geschieht, wird durch den Typ des Streams vorgegeben.
gp  Aus dem Datenstrom muss gelesen werden, ansonsten könnte man die Daten nicht weiterverarbeiten. Das Ziel kann unterschiedlich sein: Die Bytes können Variablen oder Arrays zugewiesen werden, sie könnten aber auch in einer Datenbank landen und zur Ausgabe an einem Peripheriegerät wie dem Drucker oder dem Monitor dienen.
gp  Nicht immer ist es erforderlich, den Datenstrom vom ersten bis zum letzten Byte auszuwerten. Manchmal reicht es aus, erst ab einer bestimmten Position zu lesen. Man spricht dann vom wahlfreien Zugriff.

Nicht alle Datenströme können diese drei Punkte gleichzeitig erfüllen. Beispielsweise unterstützen Datenströme im Netzwerk nicht den wahlfreien Zugriff.

Bei den Streams werden grundsätzlich zwei Typen unterschieden:

1. Base-Streams, die direkt aus einem Strom Daten lesen oder in diesen hineinschreiben. Diese Vorgänge können z.  B. in Dateien, im Hauptspeicher oder in einer Netzwerkverbindung enden.
       
2. Pass-Through-Streams ergänzen einen Base-Stream um spezielle Funktionalitäten. So können manche Streams verschlüsselt oder im Hauptspeicher gepuffert werden. Pass-Through-Streams lassen sich hintereinander in Reihe schalten, um so die Fähigkeiten eines Base-Streams zu erweitern. Auf diese Weise lassen sich sogar individuelle Streams konstruieren.
       

Galileo Computing

12.4.1 Die abstrakte Klasse »Stream«  downtop

Die Klasse Stream ist die abstrakte Basisklasse aller anderen Stream-Klassen. Sie stellt alle fundamentalen Eigenschaften und Methoden bereit, die von den abgeleiteten Klassen geerbt werden und letztendlich deren Funktionalität ausmachen.

Die von der Klasse Stream abgeleiteten Klassen unterstützen mit ihren Methoden nur Operationen auf Bytesequenzen. Da alleine durch eine Bytesequenz noch keine Aussage darüber getroffen ist, welcher Datentyp sich hinter mehreren aufeinander folgenden Bytes verbirgt, muss der Inhalt eines solchen Stroms noch interpretiert werden.

Die Eigenschaften der Klasse »Stream«

Streams stellen Schreib-, Lese- und Suchoperationen bereit. Allerdings unterstützt nicht jeder Stream gleichzeitig alle Operationen. Um in einem gegebenen Stream dessen Verhaltensweisen festzustellen, können Sie die Eigenschaften CanRead, CanWrite und CanSeek abfragen, die einen booleschen Wert zurückliefern und Auskunft über die Charakteristik dieses Stream-Objekts liefern. Die Eigenschaft Length liefert die Länge des Streams und Position die aktuelle Position innerhalb des Streams. Letztere wird allerdings nur von den Streams bereitgestellt, die auch die Positionierung mit der Seek-Methode unterstützen.


Tabelle 12.12     Eigenschaften der abstrakten Klasse »Stream«

Eigenschaft Beschreibung
CanRead Ruft in einer abgeleiteten Klasse einen Wert ab, der angibt, ob der aktuelle Stream Lesevorgänge unterstützt.
CanWrite Ruft in einer abgeleiteten Klasse einen Wert ab, der angibt, ob der aktuelle Stream Schreibvorgänge unterstützt.
CanSeek Ruft in einer abgeleiteten Klasse einen Wert ab, der angibt, ob der aktuelle Stream Suchvorgänge unterstützt.
Length Ruft in einer abgeleiteten Klasse die Länge des Streams in Byte ab.
Position Ruft in einer abgeleiteten Klasse die Position im aktuellen Stream ab oder legt diese fest.

Die Methoden der Klasse »Stream«

Die wichtigsten Methoden aller Stream-Klassen dürften Read, Write und Seek sein, die an dieser Stelle allgemein beschrieben werden sollen.

Einem schreibenden Stream müssen Sie die Daten übergeben, die in den Datenstrom geschrieben werden sollen. Die Write-Methode liest die Elemente byteweise ein und schreibt sie in den Strom. Der Empfänger des Datenstroms kann die Bytes mit Read entnehmen. Die Methode ermöglicht zudem die Festlegung der Position, ab welcher der Lese- bzw. Schreibvorgang beginnen soll.

Beachten Sie auch, dass Write keinen Rückgabewert hat, während Read einen Integer liefert, dem Sie die Anzahl der gelesenen Bytes entnehmen können, die in einen Puffer geschrieben worden sind. Der Rückgabewert ist 0, wenn das Ende des Streams erreicht ist. Er kann aber auch kleiner sein als im dritten Parameter angegeben, wenn weniger Bytes im Stream eingelesen werden.

Die Klasse Stream definiert zwei weitere, ähnliche Methoden, die jedoch jeweils nur immer ein Byte aus dem Datenstrom lesen oder in diesen hineinschreiben: ReadByte und WriteByte. Beide Methoden sind parameterlos und setzen den Positionszeiger innerhalb des Streams um eine (Byte-)Position weiter. Der Rückgabewert der ReadByte-Methode ist –1, wenn das Ende des Datenstroms erreicht ist.

Um in einem Datenstrom ab einer vorgegebenen Position zu lesen oder zu schreiben, bietet sich die Seek-Methode an, bei deren Aufruf der Startpunkt für den Positionszeiger im Stream festgelegt wird, ab dem weitere E/A-Operationen beginnen sollen. Zudem müssen Sie auch die Verschiebung der Bytes ab einer festgelegten Ursprungsposition angeben. Letztere ist vom Typ SeekOrigin, in der die folgenden drei Konstanten definiert sind.


Tabelle 12.13     Konstantenliste der Aufzählung »SeekOrigin«

Member Beschreibung
Begin Gibt den Anfang eines Streams an.
Current Gibt die aktuelle Position innerhalb eines Streams an.
End Gibt das Ende eines Streams an.

Mit SeekOrigin.Begin wird der Positionszeiger auf das erste Byte des Datenstroms gesetzt, mit SeekOrigin.Current behält er seine augenblickliche Position bei, und mit SeekOrigin.End wird er auf das Byte gesetzt, das als erstes den Bytes des vollständigen Streams folgt. Ausgehend von origin wird durch Addition von offset die gewünschte Startposition ermittelt.

Ein Stream, der einmal geöffnet worden ist und Daten in den Puffer geschrieben hat, sollte ordnungsgemäß mit Close geschlossen werden.

Sie haben jetzt einige Methoden im Schnelldurchlauf kennen gelernt. Alle erwähnten wollen wir zum Schluss in übersichtlicher tabellarischer Form zusammenfassen.


Tabelle 12.14     Methoden der abstrakten Klasse »Stream«

Methode Beschreibung
Close Schließt den aktuellen Stream und gibt alle ihm zugeordneten Ressourcen frei.
Read Liest eine Folge von Bytes aus dem aktuellen Stream und setzt den Datenzeiger im Stream um die Anzahl der gelesenen Bytes weiter.
ReadByte Liest ein Byte aus dem Stream und erhöht die Position im Stream um ein Byte. Der Rückgabewert ist –1, wenn das Ende des Streams erreicht ist.
Seek Legt die Position im aktuellen Stream fest.
Write Schreibt eine Folge von Bytes in den aktuellen Stream und erhöht den Datenzeiger im Stream um die Anzahl der geschriebenen Bytes.
WriteByte Schreibt ein Byte an die aktuelle Position im Stream und setzt den Datenzeiger um eine Position im Stream weiter.


Galileo Computing

12.4.2 Die von »Stream« abgeleiteten Klassen im Überblick  downtop

Sie haben in den vorherigen Ausführungen nur die wichtigsten Methoden und Eigenschaften der Klasse Stream kennen gelernt. Die bisherigen Aussagen sollten genügen, um eine Vorstellung davon zu erhalten, welche wesentlichen Verhaltensweisen an die abgeleiteten Klassen weitervererbt werden.

Den in der Tabelle 12.15 aufgeführten Klassen dient Stream als Basisklasse. Dabei ist die Tabelle nicht vollständig, sondern beinhaltet nur die wichtigsten Ableitungen. Beachten Sie bitte, dass die verschiedenen ableitenden Klassen nicht alle demselben Namespace angehören.


Tabelle 12.15     Die von »Stream« abgeleiteten Klassen

Stream-Typ Beschreibung
BufferedStream Die Klasse BufferedStream wird benutzt, um Daten eines anderen E/A-Datenstroms zu puffern. Ein Puffer ist ein Block von Bytes im Arbeitsspeicher des Rechners, der dazu benutzt wird, den Datenstrom zu cachen, um damit die Anzahl der Aufrufe an das Betriebssystem zu verringern. Dadurch lässt sich insgesamt die Effizienz verbessern. Diese Klasse wird immer im Zusammenhang mit anderen Klassen eingesetzt.
CryptoStream Daten, die nicht in ihrem Originalzustand in einen Strom geschrieben werden sollen, lassen sich mit der Klasse CryptoStream verschlüsseln. CryptoStream wird immer zusammen mit einem anderen Stream kombiniert.
FileStream Diese Klasse wird dazu benutzt, um Daten in Dateien des Dateisystems zu schreiben. Eine Netzwerkverbindung kann ebenfalls das Ziel dieses Datenstroms sein.
GZipStream Mit den Methoden dieser Klasse können Sie Byteströme komprimieren und dekomprimieren.
MemoryStream Meistens sind Dateien oder Netzwerkverbindungen das Ziel der Datenströme. Es kann jedoch auch sinnvoll sein, Daten bewusst temporär in den Hauptspeicher zu schreiben und sie später von dort wieder zu lesen. Viele Anwendungen arbeiten nach dem Prinzip, Daten in eine temporäre Datei zu speichern. Ein MemoryStream kann temporäre Dateien ersetzen und trägt damit zur Steigerung der Leistungsfähigkeit einer Anwendung bei, da das Schreiben und Lesen in den Hauptspeicher um ein Vielfaches schneller ist als das Schreiben auf die Festplatte.
NetworkStream Ein Datenfluss basierend auf der Klasse NetworkStream sendet die Daten basierend auf Sockets. Das Besondere an diesem Datenstrom ist, dass er nur die Fähigkeit hat, Daten vollständig in den Strom zu schreiben oder aus diesem zu lesen. Der Zugriff auf beliebige Daten innerhalb des Stroms ist nicht möglich.


Galileo Computing

12.4.3 Die Klasse »FileStream«  toptop

Die Klasse FileStream ist die universelle und damit in vielen Anwendungsfällen am geeignetsten erscheinende Klasse. Sie hat die Fähigkeit, sowohl byteweise aus einer Datei zu lesen als auch byteweise in eine Datei zu schreiben. Außerdem kann ein Positionszeiger auf eine beliebige Position innerhalb des Streams gesetzt werden. Ein FileStream puffert die Daten, um die Ausführungsgeschwindigkeit zu erhöhen. Die Größe des Puffers beträgt standardmäßig 8 kByte.

Die FileStream-Klasse bietet eine Reihe von Konstruktoren an, um dem Objekt bestimmte Verhaltensweisen und Eigenschaften mit auf den Lebensweg zu geben:


Public Sub New (String, FileMode)
Public Sub New (String, FileMode, FileAccess)
Public Sub New (String, FileMode, FileAccess, FileShare)
Public Sub New (String, FileMode, FileAccess, FileShare, Integer)
Public Sub New (String, FileMode, FileAccess, FileShare, _
Integer, Boolean)

Sie können ein FileStream-Objekt erzeugen, indem Sie im ersten Parameter eine Pfadangabe als Zeichenfolge übergeben. Der Parameter FileMode beschreibt, wie das Betriebssystem die Datei öffnen soll (FileMode.Append, FileMode.Create, FileMode.CreateNew .), FileAccess hingegen, wie auf die Datei zugegriffen werden darf (FileAccess.Read, FileAccess.Write oder FileAccess.ReadWrite). Sie haben diese Typen bereits im Abschnitt zur Klasse File kennen gelernt (siehe auch die Tabellen 12.2 und 12.3). Der Parameter vom Typ FileShare gibt an, ob ein gemeinsamer Zugriff auf die Datei möglich ist oder nicht (siehe auch Tabelle 12.4).

Der Puffer, in den ein FileStream die Daten zur Steigerung der Leistungsfähigkeit schreibt, ist standardmäßig 8 kByte groß. Mit dem Parameter vom Typ int können Sie die Größe des Puffers bei der Instanziierung beeinflussen. Mit dem letzten Parameter vom Typ Boolean kann noch angegeben werden, ob das Objekt asynchrone Zugriffe unterstützen soll. In Abschnitt 12.7 wird anhand eines Beispiels gezeigt, wie asynchrone Operationen implementiert werden.

Das Schreiben in einen »FileStream«

Das folgende Codefragment demonstriert, wie mit einem FileStream-Objekt Daten in eine Datei geschrieben werden.


Sub Main()
Dim arr() As Byte = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
Dim path As String = "C:\Testfile.txt"
Dim fs As FileStream = New FileStream(path, FileMode.Create)
fs.Write(arr, 0, arr.Length)
End Sub

Zunächst wird ein Byte-Array deklariert und mit insgesamt zehn Zahlen initialisiert. In der zweiten Anweisung wird der Dateiname, in den das Array geschrieben werden soll, festgelegt.

Bei der Instanziierung des FileStream-Objekts werden dem Konstruktor im ersten Argument der Pfad, auf dem der Stream operieren soll, und die Datei bekannt gegeben. Die Fähigkeiten dieses Streams beschreibt das zweite Argument: Die Konstante FileMode.Create teilt dem Konstruktor mit, dass das FileStream-Objekt eine neue Datei erzeugen kann oder, falls im angegebenen Pfad bereits eine gleichnamige Datei existiert, diese überschreiben soll. Mit


fs.Write(arr, 0, arr.Length)

wird der Inhalt des Arrays arr dem Stream-Objekt übergeben. Die Syntax der Methode Write der Klasse FileStream lautet wie folgt:


Public Sub Write(array As Byte(),offset As Integer,count As Integer)

Dabei haben die drei Parameter die folgende Bedeutung:


Tabelle 12.16     Die Parameter der Methode »Write« eines »FileStream«-Objekts

Parameter Beschreibung
array Ein Byte-Array, in das die übergebenen Daten gelesen werden
offset Die Indexposition im Array, bei dem die Leseoperation beginnen soll
count Die Anzahl der zu lesenden Bytes

Der Schreibvorgang des Beispiels startet mit dem ersten Array-Element. Das sagt der zweite Parameter der Write-Methode aus. Die Anzahl der zu schreibenden Bytes bestimmt der dritte Parameter – in unserem Beispiel werden alle Array-Elemente dem Datenstrom zugeführt.

Das Lesen aus einem »FileStream«

Wir wollen uns nun auch vom Erfolg unserer Bemühungen überzeugen und die Datei auswerten. Dazu wird der Programmcode des Beispiels wie folgt ergänzt:


Sub Main()
...
Dim arrRead(9) As Byte
fs.Read(arrRead, 0, 10)
Dim i As Integer
For i = 0 To arr.Length – 1
Console.WriteLine(arrRead(i))
Next
fs.Close()
End Sub

Wir deklarieren ein weiteres Array (arrRead), in das wir das Ergebnis der Leseoperation hineinschreiben. Da uns bekannt ist, wie viele Byte-Elemente sich in unserer Datei befinden (wie unfair), können wir die Array-Grenze schon im Voraus festlegen.

Nun kommt es zum Aufruf der Read-Methode. Zuerst wollen wir uns wieder die Syntax dieser Methode anschauen:


Public Overrides Function Read(array As Byte(), _
offset As Integer, count As Integer) As Intger

Die Parameter sind denen der Write-Methode sehr ähnlich. Das FileStream-Objekt, auf das die Read-Methode aufgerufen wird, repräsentiert eine bestimmte Datei. Diese wurde bereits über dem Konstruktor bekannt gegeben. Aus der Datei werden die Daten in das Array eingelesen, das durch den Parameter array beschrieben wird. Der erste der Schreiboperation zur Verfügung stehende Array-Index wird im Parameter offset angegeben, die Anzahl der aus dem FileStream zu lesenden Bytes im dritten Parameter count.

Wir wollen den ersten Byte-Wert aus dem Datenstrom in das mit 0 indizierte Element des Arrays arrRead schreiben und geben das im zweiten Parameter bekannt. Die Gesamtanzahl der zu lesenden Bytes teilen wir dem dritten Parameter mit. In einer Schleife wird danach das eingelesene Array durchlaufen und an der Konsole ausgegeben.

Starten Sie nun die Laufzeit des Programms, wird die Enttäuschung groß sein und Sie an den eigenen Programmierfähigkeiten zweifeln lassen! Denn bedauerlicherweise werden nicht die Zahlenwerte, die wir in die Datei geschrieben haben, ausgegeben, sondern nur Nullen. Haben wir etwas falsch gemacht, und, wenn ja, wie ist das zu erklären?

Der Positionszeiger

Die Schreib- bzw. Leseposition in einem Datenstrom wird durch einen Positionszeiger beschrieben. Schließlich muss der Strom wissen, auf welchem Byte die folgende Operation ausgeführt werden soll. Bei der Instanziierung eines Stream-Objekts verweist der Zeiger zunächst auf das erste Byte im Stream. Mit dem Aufruf der Write-Methode wird ein Wert daher genau in diese Position geschrieben. Anschließend wird der Positionszeiger auf die folgende Byteposition verschoben.

Dieser Vorgang wiederholt sich bei jedem Schreibvorgang, von denen es in unserem Beispiel zehn gibt, nämlich für jedes zu schreibende Array-Element einen. Am Ende, wenn wir unsere zehn Bytes in den Strom geschrieben haben, verweist der Positionszeiger auf das folgende, nun elfte Byte im Stream (siehe Abbildung 12.3). Genau das verursacht nun ein Problem. Wir rufen auf das FileStream-Objekt die Read-Methode auf und lesen ab der Position, die aktuell durch den Datenzeiger beschrieben wird. Das ist aber die elfte Stelle im Datenstrom – und nicht die erste, wie wir es eigentlich erwartet haben bzw. wie es hätte sein sollen.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 12.3     Der Positionszeiger in einem »Stream«-Objekt

Kommen wir nun zur Lösung. FileStream beerbt die Klasse Stream und hat daher auch eine Seek-Methode, mit der wir den Positionszeiger beliebig verbiegen können:


Public Overrides Function Seek(offset As Long, _
origin As SeekOrigin) As Long

Wir überlegen uns, wohin wir den Ursprung des Positionszeigers verlegen wollen – natürlich an den Anfang des Datenstroms. Also muss der zweite Parameter der Seek-Methode auf


origin = SeekOrigin.Begin

festgelegt werden (siehe dazu auch Tabelle 12.13). Nun geben wir im ersten Argument den tatsächlichen und endgültigen Startpunkt des Positionszeigers bezogen auf den im zweiten Parameter definierten Ursprung an. Er lautet 0, denn schließlich wollen wir den Zeiger auf die erste Position des Datenstroms setzen.


...
fs.Write(arr, 0, arr.Length)
...
fs.Seek(0, SeekOrigin.Begin)
fs.Read(arrRead, 0, 10)
...


Anmerkung

Natürlich wäre es auch möglich, zunächst das FileStream-Objekt zu schließen und es danach neu zu instanziieren. Damit hätten wir wieder einen Positionszeiger, der auf das erste Byte im Stream zeigt.


Wenn wir nach der Ergänzung mit Seek das Programm noch einmal starten, wird das Ergebnis wie erwartet ausgegeben.

Zum Schluss wollen wir noch einmal den gesamten Code zusammenfassen.


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 12\FileStreamDemo
' ----------------------------------------------------------
Imports System.IO
Module Module1
Sub Main()
Dim arr() As Byte = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
Dim path As String = "C:\Testfile.txt"
Dim fs As FileStream = New FileStream(path, FileMode.Create)
fs.Write(arr, 0, arr.Length)
Dim arrRead(9) As Byte
' Positionszeiger auf den Anfang des Streams setzen
fs.Seek(0, SeekOrigin.Begin)
' Stream lesen
fs.Read(arrRead, 0, 10)
Dim i As Integer
For i = 0 To arr.Length – 1
Console.WriteLine(arrRead(i))
Next
Console.ReadLine()
' FileStream schließen
fs.Close()
End Sub
End Module

Wir müssen nicht zwangsläufig das komplette Byte-Array vom ersten bis zum letzten Element in die Datei schreiben. Mit


fs.Write(arr, 2, arr.Length – 2)

ist das erste zu schreibende Element dasjenige, das die Zahl 30 enthält (entsprechend dem Index 2). Wenn wir allerdings den dritten Parameter, der die Anzahl der zu lesenden Bytes angibt, nicht entsprechend anpassen, wird über das Ende des Arrays hinausgelesen, was zu der Exception ArgumentException führt.

Eine Textdatei mit »FileStream« lesen

In Abschnitt 12.3.1 haben Sie anhand eines Beispiels gesehen, wie eine Textdatei eingelesen werden kann. In dem Beispiel (auf der Buch-CD unter \Kapitel 12\TextdateiLesen zu finden) hatten wir dazu die Klasse StreamReader benutzt. Auch mit einem FileStream-Objekt kann problemlos auf eine Textdatei zugegriffen werden. Wir wollen uns das nachfolgend ansehen:


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 12\FileStream-Textdatei
' ----------------------------------------------------------
Imports System.IO
Module Module1
Sub Main()
' Benutzereingabe anfordern
Console.Write("Geben Sie die zu öffnende Datei an: ")
Dim strFile As String = Console.ReadLine()
' prüfen, ob die angegebene Datei existiert
If Not File.Exists(strFile) Then
Console.WriteLine("Die Datei {0} existiert nicht!", strFile)
Console.ReadLine()
Return
End If
' Datei öffnen
Dim fs As FileStream = File.Open(strFile, FileMode.Open)
' Byte-Array, in das die Daten aus dem Datenstrom ein-
' gelesen werden
Dim puffer(fs.Length – 1) As Byte
' die Zeichen aus der Datei lesen und in das Array
' schreiben, der Lesevorgang beginnt mit dem ersten Zeichen
fs.Read(puffer, 0, fs.Length)
' das Byte-Array elementweise einlesen und jedes
' Array-Element in Char konvertieren
Dim i As Integer
For i = 0 To fs.Length – 1
Console.Write(Convert.ToChar(puffer(i)))
Next
Console.ReadLine()
End Sub
End Module

Nach dem Start der Laufzeit wird der Benutzer dazu aufgefordert, den Pfad zu einer Textdatei anzugeben. Diesmal beschreiten wir allerdings einen anderen Weg und rufen den Konstruktor nicht direkt auf, sondern die Methode Open der Klasse File:


Dim fs As FileStream = File.Open(strFile, FileMode.Open)

Diese Anweisung funktioniert tadellos, weil der Rückgabewert der File.Open-Methode die Referenz auf eine FileStream-Instanz liefert. Gegen den Weg über einen FileStream-Konstruktor, der diese Möglichkeit auch bietet, ist zwar grundsätzlich nichts einzuwenden, wir wollen uns allerdings die gezeigte Alternative vor Augen führen.

Im folgenden Schritt wird das Byte-Array puffer deklariert und mit einer Kapazität initialisiert, die der Größe der Datei entspricht:


Dim puffer(fs.Length – 1) As Byte

Die Größe der Datei besorgen wir uns mit der Eigenschaft Length der Klasse FileStream, die uns die Größe des Datenstroms liefert. Daran schließt sich die Leseoperation mit Read an, die den Inhalt der Textdatei byteweise liest und in das Array puffer schreibt:


fs.Read(puffer, 0, fs.Length)

Ein FileStream-Objekt arbeitet grundsätzlich nur auf der Basis von Bytes, es weiß nichts von dem tatsächlichen Typ, der sich im Datenstrom verbirgt. Eine Textdatei enthält aber Zeichen, die als ANSI-Zeichen interpretiert erst den wirklichen Informationsgehalt liefern. Deshalb müssen wir jedes einzelne Byte des Streams in einen Char-Typ konvertieren. Das geschieht in einer Schleife, die alle Bytes des Arrays abgreift, konvertiert und danach an der Konsole ausgibt.


For i = 0 To fs.Length – 1
Console.Write(Convert.ToChar(puffer(i)))
Next

Würden die Daten aus der Datei einem anderen Typ zugrunde liegen, beispielsweise Integer oder Single, müsste dieser Zieldatentyp angegeben werden. Wissen Sie nicht, welcher Typ in der Datei gespeichert ist, können Sie mit dem Inhalt praktisch nichts anfangen.

 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de